/*
 * SaxonXQueryImplementation.java
 *
 * Created on March 21, 2007, 2:46 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package com.smallx.xproc.library.saxon;

import com.smallx.xproc.library.XQueryComponentDefinition;
import java.net.URI;
import javax.xml.transform.sax.SAXResult;
import net.sf.saxon.Configuration;
import net.sf.saxon.event.PipelineConfiguration;
import net.sf.saxon.query.DynamicQueryContext;
import net.sf.saxon.query.StaticQueryContext;
import net.sf.saxon.query.XQueryExpression;
import net.sf.saxon.tinytree.TinyBuilder;
import net.sf.saxon.trans.XPathException;
import org.infoset.xml.InfosetFactory;
import org.infoset.xml.ItemDestination;
import org.infoset.xml.XMLException;
import org.infoset.xml.sax.SAXEventGenerator;
import org.infoset.xml.util.SerializerDestination;

/**
 *
 * @author alex
 */
public class SaxonXQueryImplementation implements XQueryComponentDefinition.Implementation {
    
   class SaxonExpression implements XQueryComponentDefinition.Expression {
      XQueryExpression expr;
      TinyBuilder tbuilder;
      SaxonExpression(XQueryExpression expr) {
         this.expr = expr;
      }
      public ItemDestination getContext()
         throws XMLException
      {
         tbuilder = new TinyBuilder();
         PipelineConfiguration pipeConfig = config.makePipelineConfiguration();
         pipeConfig.setConfiguration(config);
         tbuilder.setPipelineConfiguration(pipeConfig);
         return new SerializerDestination(new BuilderSerializer(config,tbuilder));
      }
      
      public void eval(URI baseURI,ItemDestination output)
         throws XMLException
      {
         try {
            DynamicQueryContext dcontext = new DynamicQueryContext(config);
            dcontext.setContextNode(tbuilder.getCurrentRoot());
            SAXEventGenerator eventGenerator = new SAXEventGenerator();
            eventGenerator.setItemConstructor(InfosetFactory.getDefaultInfoset().createItemConstructor(baseURI));
            eventGenerator.setItemDestination(output);
            SAXResult result =  new SAXResult(eventGenerator);
            if (baseURI!=null) {
               result.setSystemId(baseURI.toString());
            }
            expr.run(dcontext,result,null);
         } catch (XPathException ex) {
            throw new XMLException("Cannot evaluate XQuery: "+ex.getMessage(),ex);
         }
      }
   }

   Configuration config = new Configuration();
   StaticQueryContext staticContext;
   /** Creates a new instance of SaxonXQueryImplementation */
   public SaxonXQueryImplementation()
   {
      staticContext = new StaticQueryContext(config);
   }
   
   public XQueryComponentDefinition.Expression compile(URI baseURI,String expr)
      throws XMLException
   {
      try {
         XQueryExpression saxonExpr;
         synchronized (staticContext) {
            staticContext.setBaseURI(baseURI.toString());
            saxonExpr = staticContext.compileQuery(expr);
         }
         return new SaxonExpression(saxonExpr);
      } catch (XPathException ex) {
         throw new XMLException("Cannot compile XQuery: "+ex.getMessage(),ex);
      }
   }
   
}

